package tools

import (
	"crypto/md5"
	"encoding/hex"
	"errors"
	"mime/multipart"
	"os"
	"path"
	"strconv"
	"strings"

	"github.com/aliyun/aliyun-oss-go-sdk/oss"
	"github.com/gin-gonic/gin"
	. "github.com/hunterhug/go_image"
)

/*
 +----------------------------------------------------------------------
 + Title        : OSS图片上传
 + Author       : huwl
 + Version      : 1.0.0
 + Initial-Time : 2021-09-22
 + Last-time    : 这个文件最后修改的时间 + 修改人的名称
 + Desc         : OSS图片上传
 +----------------------------------------------------------------------
*/
type OssSingleUploadImage struct{}

// oss 配置信息
type OssConf struct {
	EndPoint        string `yaml:"end_point" json:"end_point"`
	AccessKeyId     string `yaml:"access_key_id" json:"access_key_id"`
	AccessKeySecret string `yaml:"access_key_secret" json:"access_key_secret"`
	Bucket          string `yaml:"bucket" json:"bucket"`
}

// 临时存储上传路径
var tempStoreUploadPath string = "./static/upload_images/"

/**
 * OSS上传单张图片
 *
 * @param *gin.Context ctx --------------------------------------------必传
 * @param *multipart.FileHeader image ---------------------------------必传
 * @param string tag --------------------------------------------------必传
 * @param []map[string]string thumbs ----------------------------------必传
 * @param map[string]string water -------------------------------------必传
 * @return map[string]interface{}, error
 * @author huwl
 */
func (o *OssSingleUploadImage) OssSingleImageUpload(ctx *gin.Context, image *multipart.FileHeader, tag string, thumbs []map[string]string, water map[string]string) (map[string]interface{}, error) {
	imageExt := path.Ext(image.Filename)
	allowExtMap := map[string]bool{
		".jpg":  true,
		".png":  true,
		".gif":  true,
		".jepg": true,
	}

	if !allowExtMap[imageExt] {
		return nil, errors.New("图片类型错误仅支持jpg/png/gif/jepg")
	}

	filepath := tempStoreUploadPath + GetDay()
	err := os.MkdirAll(filepath, 0755)
	if err != nil {
		return nil, errors.New("创建目录错误")
	}

	filename := strconv.FormatInt(GetUnix(), 10)
	h := md5.New()
	h.Write([]byte(filename)) // 需要加密的字符串
	filename = hex.EncodeToString(h.Sum(nil)) + imageExt
	imagePath := filepath + "/" + filename

	// 上传文件到指定的路径
	err = ctx.SaveUploadedFile(image, imagePath)
	if err != nil {
		return nil, errors.New("上传图片失败")
	}

	thumbUrls := []map[string]string{}
	if len(thumbs) > 0 {
		for _, thumb := range thumbs {
			imageUrl := filepath + "/thumb-" + thumb["width"] + "X" + thumb["height"] + filename
			width, _ := strconv.Atoi(thumb["width"])
			height, _ := strconv.Atoi(thumb["height"])
			err = ThumbnailF2F(imagePath, imageUrl, width, height)
			if err != nil {
				return nil, err
			}

			thumbUrl := map[string]string{}
			thumbUrl["image_url"] = strings.TrimLeft(imageUrl, ".")
			thumbUrl["image_name"] = "/thumb-" + thumb["width"] + "X" + thumb["height"] + filename
			thumbUrls = append(thumbUrls, thumbUrl)
		}
	}

	ossConf := &OssConf{}
	// +++++++++++++++++ 使用本地配置方式开始 +++++++++++++++++
	// cfg, err := GetConfig("oss", "yml")
	// if err != nil {
	// 	return nil, err
	// }
	// ossConf.EndPoint = cfg.GetString(Env + ".endpoint")
	// ossConf.AccessKeyId = cfg.GetString(Env + ".access_key_id")
	// ossConf.AccessKeySecret = cfg.GetString(Env + ".access_key_secret")
	// ossConf.Bucket = cfg.GetString(Env + ".bucket")
	// +++++++++++++++++ 使用本地配置方式结束 +++++++++++++++++

	// +++++++++++++++++ 使用配置中心方式开始 +++++++++++++++++
	InitConfigCenter(OssConfigCenter, ossConf)
	// +++++++++++++++++ 使用配置中心方式结束 +++++++++++++++++

	client, err := oss.New(
		ossConf.EndPoint,
		ossConf.AccessKeyId,
		ossConf.AccessKeySecret,
	)
	if err != nil {
		os.Remove(imagePath)
		return nil, err
	}

	// 填写存储空间名称，例如examplebucket。
	bucket, err := client.Bucket(ossConf.Bucket)
	if err != nil {
		os.Remove(imagePath)
		return nil, err
	}

	// 依次填写Object的完整路径（例如exampledir/exampleobject.txt）和本地文件的完整路径（例如D:\\localpath\\examplefile.txt）。
	err = bucket.PutObjectFromFile(tag+"/"+filename, imagePath)
	os.Remove(imagePath)
	if err != nil {
		return nil, err
	}

	thumbImages := []map[string]string{}
	for _, v := range thumbUrls {
		err = bucket.PutObjectFromFile(tag+v["image_name"], "."+v["image_url"])
		os.Remove("." + v["image_url"])
		if err != nil {
			return nil, err
		}

		thumbImages = append(thumbImages, map[string]string{
			"image_url":          tag + v["image_name"],
			"absolute_image_url": ossConf.Bucket + "." + ossConf.EndPoint + "/" + tag + v["image_name"],
		})
	}

	return map[string]interface{}{
		"image_url":          tag + "/" + filename,
		"absolute_image_url": ossConf.Bucket + "." + ossConf.EndPoint + "/" + tag + "/" + filename,
		"thumb_images":       thumbImages,
	}, nil
}
